본문으로 건너뛰기

Dynamic Routes

정보

다음은 Next.js 공식 문서를 참고한 글입니다.

배울 내용


Page Path Depends on External Data


들어가기에 앞서

  • 외부 데이터에 의존하는 경로가 있는 페이지를 정적으로 생성할 수 있다.
  • 이를 통해 Next.js에서 동적 URL이 활성화됩니다.

동적 경로로 페이지를 생성하는 방법

  • 각 게시물의 경로를 갖기 위해 /posts/\<id>의 형태로 구현한다. 여기서 id는 최상위 posts 디렉토리 하위에 있는 마크다운 파일 이름이다.
  • pages/posts 아래에 [id].js 라는 페이지를 생성한다. [로 시작되어 ]로 끝나는 경우 Next.js에서 동적 경로로 사용된다.
  • pages/posts/[id].js 소스코드 작성
import Layout from '../../components/layout';

export default function Post() {
return <Layout>...</Layout>;
}

export async function getStaticPaths() {
// id 값 반환 메서드
}

export async function getStaticProps({ params }) {
// params.id를 사용하여 블로그 게시물에 필요한 데이터를 가져오기
}

getStaticPaths 구현


구현하기

  • pages/posts 내부에 [id].js 생성
  • pages/posts 내부에 있는 first-post.js 삭제
  • lib/posts.js 구현
export function getAllPostIds() {
const fileNames = fs.readdirSync(postsDirectory);

// Returns an array that looks like this:
// [
// {
// params: {
// id: 'ssg-ssr'
// }
// },
// {
// params: {
// id: 'pre-rendering'
// }
// }
// ]
return fileNames.map((fileName) => {
return {
params: {
id: fileName.replace(/\.md$/, ''),
},
};
});
}

중요 : 반환된 목록은 단순한 문자열 배열이 아니라 위의 주석처럼 보이는 개체 배열이어야 한다 . 각 개체에는 키가 있어야 하며 키가 params있는 개체를 포함해야 한다. ( 파일 이름에 id사용하기 때문 ). 그렇지 않으면 getStaticPaths가 실패한다.

  • getAllPostIds 구현
import { getAllPostIds } from '../../lib/posts';

export async function getStaticPaths() {
const paths = getAllPostIds();
return {
paths,
fallback: false,
};
}
  • getStaticPaths적용
import { getAllPostIds } from '../../lib/posts';
space
export async function getStaticPaths() {
const paths = getAllPostIds();
return {
paths,
fallback: false,
};
}

getStaticProps 구현


getPostDate 구현

  • 주어진 ID로 게시물을 렌더링하는 데 필요한 데이터를 가져와야 한다.
export function getPostData(id) {
const fullPath = path.join(postsDirectory, `${id}.md`);
const fileContents = fs.readFileSync(fullPath, 'utf8');

// Use gray-matter to parse the post metadata section
const matterResult = matter(fileContents);

// Combine the data with the id
return {
id,
...matterResult.data,
};
}

getStaticProps를 통해 데이터 불러오기

import { getAllPostIds, getPostData } from '../../lib/posts';

export async function getStaticProps({ params }) {
const postData = getPostData(params.id);
return {
props: {
postData,
},
};
}

POST 컴포넌트 적용

export default function Post({ postData }) {
return (
<Layout>
{postData.title}
<br />
{postData.id}
<br />
{postData.date}
</Layout>
);
}

Polishing the Post Page


pages 내부 index.js 코드 작성

  • 링크 및 날짜 적용
<li className={utilStyles.listItem} key={id}>
<Link href={`/posts/${id}`}>{title}</Link>
<br />
<small className={utilStyles.lightText}>
<Date dateString={date} />
</small>
</li>

Dynamic Routes Details


외부 API 가져오기 or 데이터베이스 쿼리

  • getStaticProps와 마찬가지로 getStaticPaths는 모든 데이터 소스에서 데이터를 가져올 수 있다.
  • 다음 예제에서 getAllPostIds(getStaticPaths에서 사용됨)는 외부 API 엔드포인트에서 가져온다.
export async function getAllPostIds() {
// Instead of the file system,
// fetch post data from an external API endpoint
const res = await fetch('..');
const posts = await res.json();
return posts.map((post) => {
return {
params: {
id: post.id,
},
};
});
}

Development vs. Production

  • 개발 모드에서는 모든 요청에서 getStaticPath가 실행된다.
  • 운영 모드에서는 빌드에만 작동한다.

Fallback

  • 폴백이 거짓이면 getStaticPaths에서 반환되지 않은 모든 경로는 404 페이지가 된다.
  • 폴백이 참이면 getStaticProps의 동작이 변경된다.
    • getStaticPaths에서 반환된 경로는 빌드 시 HTML로 렌더링된다.
    • 빌드 시점에 생성되지 않은 경로는 404 페이지가 생성되지 않는다. 대신 Next.js는 해당 경로에 대한 첫 번째 요청 시 페이지의 "폴백" 버전을 제공한다.
    • 백그라운드에서 Next.js는 요청된 경로를 정적으로 생성한다. 동일한 경로에 대한 후속 요청은 빌드 시점에 미리 렌더링된 다른 페이지와 마찬가지로 생성된 페이지를 제공한다.
  • 폴백이 차단되는 경우 새 경로는 getStaticProps를 사용하여 서버 측에서 렌더링되고 향후 요청을 위해 캐시되므로 경로당 한 번만 발생한다.

Catch-all Routes

  • 동적 경로는 괄호 안에 점 세개(…)를 추가하여 모든 경로를 포착하도록 확장할 수 있다.
  • pages/posts/[...id].js는 /posts/a뿐만 아니라 /posts/a/b, /posts/a/b/c 등과도 일치한다.

Router

  • Next.js 라우터에 액세스하려면 next/router에서 useRouter 훅을 가져와 액세스할 수 있다.

404 Pages

  • 사용자 정의 404 페이지를 만들려면 pages/404.js를 생성한다.
  • 이 파일은 빌드 시점에 정적으로 생성된다.